frontend/pages/e/[uuid].tsx (view raw)
1import {useState, useReducer, useEffect} from 'react';
2import {useTranslation} from 'react-i18next';
3import Layout from '../../layouts/Default';
4import Fab from '../../containers/Fab';
5import CarColumns from '../../containers/CarColumns';
6import NewCarDialog from '../../containers/NewCarDialog';
7import AddToMyEventDialog from '../../containers/AddToMyEventDialog';
8import EventBar from '../../containers/EventBar';
9import useToastStore from '../../stores/useToastStore';
10import {initializeApollo} from '../../lib/apolloClient';
11import ErrorPage from '../_error';
12import {
13 useUpdateEventMutation,
14 Event as EventType,
15 useEventByUuidQuery,
16 EventByUuidDocument,
17} from '../../generated/graphql';
18import useEventStore from '../../stores/useEventStore';
19import Loading from '../../containers/Loading';
20
21interface Props {
22 event: EventType;
23 eventUUID: string;
24}
25
26const EventPage = props => {
27 const {event} = props;
28 const {t} = useTranslation();
29
30 if (!event) return <ErrorPage statusCode={404} title={t`event.not_found`} />;
31
32 return <Event {...props} />;
33};
34
35const Event = (props: Props) => {
36 const {eventUUID} = props;
37 const {t} = useTranslation();
38 const addToast = useToastStore(s => s.addToast);
39 const setEvent = useEventStore(s => s.setEvent);
40 const eventUpdate = useEventStore(s => s.event);
41 const setIsEditing = useEventStore(s => s.setIsEditing);
42 const [updateEvent] = useUpdateEventMutation();
43 const [isAddToMyEvent, setIsAddToMyEvent] = useState(false);
44 const [openNewCar, toggleNewCar] = useReducer(i => !i, false);
45 const {data: {eventByUUID: event} = {}} = useEventByUuidQuery({
46 variables: {uuid: eventUUID},
47 });
48
49 useEffect(() => {
50 if (event) setEvent(event as EventType);
51 }, [event]);
52
53 const onSave = async e => {
54 try {
55 const {id, ...data} = eventUpdate;
56 delete data.__typename;
57 delete data.cars;
58 await updateEvent({variables: {id, eventUpdate: data}});
59 setIsEditing(false);
60 } catch (error) {
61 console.error(error);
62 addToast(t('event.errors.cant_update'));
63 }
64 };
65
66 const onShare = async () => {
67 if (!event) return null;
68 // If navigator as share capability
69 if (!!navigator.share)
70 return await navigator.share({
71 title: `Caroster ${event.name}`,
72 url: `${window.location.href}`,
73 });
74 // Else copy URL in clipboard
75 else if (!!navigator.clipboard) {
76 await navigator.clipboard.writeText(window.location.href);
77 addToast(t('event.actions.copied'));
78 return true;
79 }
80 };
81
82 if (!event) return <Loading />;
83
84 return (
85 <Layout
86 pageTitle={t('event.title', {title: event.name})}
87 menuTitle={t('event.title', {title: event.name})}
88 displayMenu={false}
89 >
90 <EventBar
91 event={event}
92 onAdd={setIsAddToMyEvent}
93 onSave={onSave}
94 onShare={onShare}
95 />
96 <CarColumns toggleNewCar={toggleNewCar} />
97 <Fab onClick={toggleNewCar} open={openNewCar} aria-label="add-car" />
98 <NewCarDialog open={openNewCar} toggle={toggleNewCar} />
99 <AddToMyEventDialog
100 event={event}
101 open={isAddToMyEvent}
102 onClose={() => setIsAddToMyEvent(false)}
103 />
104 </Layout>
105 );
106};
107
108export async function getServerSideProps(ctx) {
109 const {uuid} = ctx.query;
110 const apolloClient = initializeApollo();
111 const {data = {}} = await apolloClient.query({
112 query: EventByUuidDocument,
113 variables: {uuid},
114 });
115 const {eventByUUID: event} = data;
116 const {host = ''} = ctx.req.headers;
117
118 return {
119 props: {
120 event,
121 eventUUID: uuid,
122 metas: {
123 title: event?.name || '',
124 url: `https://${host}${ctx.resolvedUrl}`,
125 },
126 },
127 };
128}
129
130export default EventPage;